#include <iostream>
#include "udpserver.hpp"
#include "Thread.hpp"
#include "comm.hpp"
using namespace ThreadModule;
void usage(std::string str)
{
    std::cout << "usage: " << str << "  server_ip server_port" << std::endl;
}

int init_client(const std::string &server_ip, uint16_t server_port, struct sockaddr_in *local)
{
    int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd < 0)
    {
        LOG(FATAL, "socket error ,%s,%d\n", strerror(errno), errno);
        exit(SOCKET_ERROR);
    }
    memset(local, 0, sizeof(struct sockaddr_in));
    local->sin_family = AF_INET;
    local->sin_port = htons(server_port);//主机端口转网络端口
    local->sin_addr.s_addr = inet_addr(server_ip.c_str());
    return sockfd;
}
void recv_message(int sockfd, std::string name)
{
    // int fd = OpenDev("/dev/pts/1", O_WRONLY);
    while (true)
    {
        struct sockaddr_in peer;
        socklen_t len = sizeof(peer);
        char buffer[1024];
        ssize_t n = recvfrom(sockfd, buffer, sizeof(buffer) - 1, 0, (struct sockaddr *)&peer, &len);
        if (n > 0)  
        {
            buffer[n] = 0;
            fprintf(stderr, "[%s]%s\n", name.c_str(), buffer); // 将收到的信息向标准错误中写入
            // write(fd, buffer, strlen(buffer));//将收到的信息向fd中写入
        }
    }
}
void send_message(int sockfd, struct sockaddr_in &local, std::string name)
{
    std::string message;
    while (true)
    {
        printf("%s | enter$", name.c_str());
        fflush(stdout);
        std::getline(std::cin, message);
        sendto(sockfd, message.c_str(), message.size(), 0, (struct sockaddr *)&local, sizeof(local));
    }
}
int main(int argc, char *argv[])
{
    if (argc != 3)
    {
        usage(argv[0]);
        exit(USAGE_ERROR);
    }
    std::string server_ip = argv[1];
    uint16_t server_port = std::stoi(argv[2]);
    struct sockaddr_in local; // struct sockaddr_in 系统提供的数据类型用于IPv4。local是变量，用户栈上开辟空间。
    int sockfd = init_client(server_ip, server_port, &local);
    if (sockfd == -1)
    {
        return 1;
    }
    func_t r = std::bind(&recv_message, sockfd, std::placeholders::_1);
    func_t s = std::bind(&send_message, sockfd, local, std::placeholders::_1);
    // 创建两个线程分别执行收发信息
    Thread Recver(r, "recver");
    Thread Sender(s, "sender");
    Recver.Start();
    Sender.Start();
    Recver.Join();
    Sender.Join();
    return 0;
}